﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace AlgoHero.Modelo
{
    public class Nivel
    {
        private int cantidadDeTeclasPerdidas;
        private bool nivelTerminado;

        public bool NivelTerminado
        {
            get { return this.cronometro.TiempoElapsado()>this.cancion.Duracion+this.tiempoDespuesDelFinal; }
        }
        public int CantidadDeTeclasPerdidas
        {
            get { return cantidadDeTeclasPerdidas; }
            set { cantidadDeTeclasPerdidas = value; }
        }
        private int puntajePorTecla;
        private int puntajeDeNivel;
        private bool hayNotasParaTocar;
        private Acorde acordeParaTocar;
        private double tiempoDeToleranciaAlApretar;
        private double tiempoDespuesDelFinal;

        public bool HayNotasParaTocar
        {
            get { return hayNotasParaTocar; }
            set { hayNotasParaTocar = value; }
        }

        public int PuntajeDeNivel
        {
            get { return puntajeDeNivel; }
            set { puntajeDeNivel = value; }
        }
        private Cancion cancion;
        private Cronometro cronometro;

        public Nivel(Cancion cancion)
        {
            this.hayNotasParaTocar = false;
            this.cancion = cancion;
            this.cronometro = new Cronometro();
            this.puntajePorTecla = 5;
            this.puntajeDeNivel = 0;
            this.cantidadDeTeclasPerdidas = 0;
            this.tiempoDeToleranciaAlApretar = 0.4;
            this.nivelTerminado = false;
            this.tiempoDespuesDelFinal = 5;
        }

        public void ComenzarNivel()
        {
            this.cronometro.Comenzar();
        }

        public void ReanudarNivel()
        {
            this.cronometro.Reanudar();
        }

        public void PausarNivel()
        {
            this.cronometro.Pausar();
        }

        public bool HayParaHacerJugada()
        {                                                              
            IList<Tecla> teclasCorrespondientes;
            try
            {
                teclasCorrespondientes = this.cancion.ObtenerTeclasAPresionar(this.cronometro.TiempoElapsado(), this.tiempoDeToleranciaAlApretar);
            }
            catch (TiempoInvalidoException e)
            {
                this.nivelTerminado = true;
                return false;
            }
            if (teclasCorrespondientes == null)
            {
                return false;
            }

            return true;
        }

        public void ProcesaTeclasJugadas(IList<Tecla> teclasJugadas)
        {


            IList<Tecla> teclasCorrespondientes = null;
            try
            {
                teclasCorrespondientes = this.cancion.ObtenerTeclasAPresionar(this.cronometro.TiempoElapsado(), this.tiempoDeToleranciaAlApretar);
            }
            catch (TiempoInvalidoException e)
            {
                throw new TiempoInvalidoException(e.Message);
            }
            if (teclasCorrespondientes != null)
            {
                foreach (Tecla teclaCorrespondiente in teclasCorrespondientes)
                {
                    if (!teclaCorrespondiente.FueApretada && teclasJugadas.Contains(teclaCorrespondiente))
                    {

                        this.puntajeDeNivel += this.puntajePorTecla;
                        teclaCorrespondiente.FueApretada = true;

                        if (!this.hayNotasParaTocar)
                        {
                            this.hayNotasParaTocar = true;
                            acordeParaTocar = this.cancion.ObtenerAcordePara(this.cronometro.TiempoElapsado());
                        }

                    }
                }
            }
             
            
        }

        public void ActualizarCantidadDeTeclasPerdidas()
        {
            this.cantidadDeTeclasPerdidas = this.cancion.DameCantidadDeTeclasPerdidas(this.cronometro.TiempoElapsado());
        }

        public double dameElTiempoFisicoDeCompas()
        {
            return this.cancion.TiempoDeCompas;
        }

        public int dameElTiempoMusicalDeCompas()
        {
            return this.cancion.Partitura.DuracionDeCompas;
        }

        public Acorde dameElAcordeParaTocar()
        {

            this.HayNotasParaTocar = false;
            return this.acordeParaTocar;
        }

    }
}
